package com.qen.common;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import org.beetl.sql.annotation.entity.Table;
import org.beetl.sql.clazz.ColDesc;
import org.beetl.sql.clazz.TableDesc;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;

/**
 * <p>
 * 实体类反射表辅助类
 * </p>
 *
 * @author licz
 * @since 1.0.0
 */
@Component
public class TableInfoHelper {

    private static final Set<Class<?>> SIMPLE_TYPE_SET = new HashSet();

    static {
        SIMPLE_TYPE_SET.add(String.class);
        SIMPLE_TYPE_SET.add(Byte.class);
        SIMPLE_TYPE_SET.add(Short.class);
        SIMPLE_TYPE_SET.add(Character.class);
        SIMPLE_TYPE_SET.add(Integer.class);
        SIMPLE_TYPE_SET.add(Long.class);
        SIMPLE_TYPE_SET.add(Float.class);
        SIMPLE_TYPE_SET.add(Double.class);
        SIMPLE_TYPE_SET.add(Boolean.class);
        SIMPLE_TYPE_SET.add(Date.class);
        SIMPLE_TYPE_SET.add(Class.class);
        SIMPLE_TYPE_SET.add(BigInteger.class);
        SIMPLE_TYPE_SET.add(BigDecimal.class);
    }

    /**
     * <p>
     * 获取实体映射表信息
     * </p>
     *
     * @param clazz 反射实体类
     * @return 数据库表反射信息
     */
    public static TableDesc getTableInfo(Class<?> clazz) {
        if (clazz == null || clazz.isPrimitive() || SIMPLE_TYPE_SET.contains(clazz) || clazz.isInterface()) {
            return null;
        }
        String tableName = clazz.getAnnotation(Table.class).name();
//        return TABLE_DESC_CACHE.get(tableName);
        return BeetlUtils.getSQLManager().getTableDesc(tableName);
    }

    /**
     * 获取需要进行查询的 select sql 片段
     *
     * @param predicate 过滤条件
     * @return sql 片段
     */
    public static String chooseSelect(TableDesc table, Predicate<ColDesc> predicate, List<String> noSelectProperty) {
        StringBuilder sql = new StringBuilder();
        List<String> list = new ArrayList<>();
        List<String> noSelect = Optional.of(noSelectProperty).orElse(new ArrayList<>());
        table.getColsDetail().forEach((colName, colDesc) -> {
            if (predicate.test((ColDesc) colDesc) && !noSelect.contains(colName)) {
                list.add(colName);
            }
        });
        if (CollectionUtil.isEmpty(list)) {
            return "";
        }
        for (int i = 0; i < list.size(); i++) {
            sql.append(list.get(i));
            if (i > 0) {
                sql.append(StrUtil.COMMA);
            }
        }
        return sql.toString();
    }

    /**
     * 获取需要进行查询的 select sql 片段
     *
     * @param predicate 过滤条件
     * @return sql 片段
     */
    public static String chooseSelect(TableDesc table, Predicate<ColDesc> predicate) {
        return chooseSelect(table, predicate, new ArrayList<>());
    }


    @FunctionalInterface
    private interface PropertySelector {
        boolean selection(String property);
    }

}
